
import React, { memo, useState, useMemo, useEffect } from 'react';
import { View, Text, Button, Input, Picker, } from '@tarojs/components'
import { useForm, Controller } from "react-hook-form";
import { useAsyncEffect } from "ahooks";
import { AtIcon, AtImagePicker, AtTextarea } from 'taro-ui'
import Taro, { useDidShow } from '@tarojs/taro';
import { upload } from '../../utils/request'
import ListPicker from '../ListPicker';
import AddListPicker from '../AddListPicker';
import { imgurl } from '../../utils/pathconfig'
import "taro-ui/dist/style/components/textarea.scss";
import "taro-ui/dist/style/components/icon.scss" // 按需引入
import "taro-ui/dist/style/components/image-picker.scss" // 按需引入
import './index.less'//样式


let ControlDom = ({ children, it, type, title, control, required, errors, column }) => (
    <View className='controldom'>
        <View className='itemdom' key={it} style={{ border: column && "none" }}>
            <View className="itemleft">
                {(required) && <View style={{ color: "red", marginTop: 6, marginRight: 4 }}>*</View>}
                <Text className="subbody">
                    {title}
                </Text>
                {(errors[it]) && <AtIcon value={'alert-circle'} size={16} color='red'></AtIcon>}
            </View>
            <View className="itemright">
                {
                    column ?
                        column() :
                        <Controller
                            control={control}
                            rules={{
                                required,
                            }}
                            render={({ field: { onChange, onBlur, value } }) => React.cloneElement(children, { onChange, onBlur, value })}
                            name={it}
                        />
                }

            </View>
        </View>
        {
            column ? <Controller
                control={control}
                rules={{
                    required,
                }}
                render={({ field: { onChange, onBlur, value } }) => React.cloneElement(children, { onChange, onBlur, value })}
                name={it}
            /> : null
        }
    </View>
), RenderInput = ({ onChange, onBlur, value, item }) => (
    <Input
        style={{ textAlign: "right", fontSize: 16, width: "100%", color: "#6190E8" }}
        placeholder="请输入"
        onBlur={onBlur}
        password={item?.type == "password"}
        onInput={onChange}
        value={value}
        type={item.inputtype ?? 'text'}
        disabled={item.disabled}
    />
), RenderTextarea = ({ onChange, onBlur, value, item }) => (
    <AtTextarea
        style={{ fontSize: 16, color: "#6190E8" }}
        onBlur={onBlur}
        value={value}
        onChange={onChange}
        maxLength={600}
        placeholder='请输入...'
    />
), RenderSelect = ({ onChange, onBlur, value, item, setValue, setigger, option }) => (
    <View className='spread'>
        <Picker
            onChange={(e) => {
                if (item?.linked && item.linked.length > 0) {
                    item?.linked.map(name => {
                        setValue(name, null, {
                            shouldValidate: true,
                            shouldDirty: true
                        })
                    });
                    setigger(new Date().getTime())

                }
                let index = e.detail.value;
                let val = option[item?.name[0]][index].value;
                //tigger value change
                if (item.update) {
                    let { database, effectItems, paramskey } = item.update;
                    database({ [paramskey]: val }, (res) => {
                        let text = effectItems[0] == "repairContent" ? (res?.data?.data?.faultSolution ?? "") : (res?.data?.data?.faultPhenomenon ?? "")
                        effectItems.map(it => {
                            setValue(it, text)
                        })
                    });
                }
                onChange(val)
            }}
            //style={{ marginTop: 10 }}
            mode={item?.multiple ? "multiSelector" : "selector"}
            multiSelector
            rangeKey={"label"}
            range={option[item?.name[0]] ?? []}

        >
            <View className='picker' style={{ color: "#6190E8" }}>
                {option[item?.name[0]] ?
                    option[item?.name[0]].filter((it, i) => {
                        return it.value == value
                    })[0]?.label ?? <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>
                    : <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>}
            </View>
        </Picker>
        <View style={{ width: 6, height: 6 }}>

        </View>
        {
            value && <AtIcon value={'close-circle'} size={18} color='#000' onClick={() => {
                if (item?.linked && item.linked.length > 0) {
                    item?.linked.map(name => {
                        setValue(name, null, {
                            shouldValidate: true,
                            shouldDirty: true
                        })
                    });
                    setigger(new Date().getTime())
                }
                onChange(null)
            }}></AtIcon>
        }

    </View>
), RenderDatePicker = ({ onChange, onBlur, value, item, setValue, setigger, option }) => {
    return (
        <Picker
            mode={item?.showTime ? "time" : "date"}
            fields={item.fields}
            end={item.end ?? "2999-01-01"}
            start={item.start ?? "1970-01-01"}
            onChange={(e) => {
                onChange(e.detail.value)
            }}>
            <View className='picker' style={{ color: "#6190E8" }}>{value ?? <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>}</View>
        </Picker>
    )
}, RenderImagePicker = ({ onChange, onBlur, value, item, setValue, setigger, option }) => (
    <View style={{ margin: "10rpx -20rpx 10rpx -20rpx" }}>
        <AtImagePicker
            count={item.limit - (value ? value.length : 0)}
            length={4}
            showAddBtn={value && value.length < item.limit}
            files={value}
            multiple={true}
            onChange={(files, operationType, index) => {
                let values = value ?? [];
                if (operationType == "remove") {
                    onChange(values.filter((it, i) => { return i.toString() !== index.toString() }));
                    return;
                }

                files.map(it => {
                    upload(it.url, {}, (res) => {
                        let curdata = JSON.parse(res) ?? {},
                            cur = curdata?.data?.dataList[0] ?? {};
                        cur.url = imgurl + cur.url;
                        values = [...values, cur];
                        onChange(values)
                    })
                })
            }}
            onFail={() => {

            }}
            onImageClick={(index, file) => {
                Taro.previewImage({
                    current: file.url, // 当前显示图片的http链接
                    urls: value.map(it => it.url) // 需要预览的图片http链接列表
                })
            }}
        />
    </View>

), RenderList = memo(({ onChange, onBlur, value, item, setValue, setigger, option }) => {
    let alldata = item?.dataSource ? item?.dataSource.map(it => ({
        id: it.id
    })) : []
    let newColumns = item?.columns.map(it => {
        if (it?.submittype) {
            return {
                ...it,
                render: (cur, row) => {
                    let judge = it.judge ?? [], //判断规则
                        ifs = row[it?.submittype],//判断条件
                        curtype = judge.filter(it => it?.val == ifs)[0];//当前规则
                    let { key, type } = curtype ?? {};//结构结果
                    let newvalue = value ?? alldata,//初始化idlist
                        curval = newvalue.filter(it => it.id == row.id)[0];//当前行val
                    curval = curval ?? {};
                    if (type == "select") {
                        return <View height={20}>
                            <Picker
                                onChange={(e) => {
                                    let index = parseInt(e.detail.value);
                                    let val = it.options[index].value;
                                    let changeval = newvalue.map(it => {
                                        if (it.id == row.id) {
                                            return {
                                                ...it,
                                                [key]: val
                                            }
                                        } else {
                                            return {
                                                ...it
                                            }
                                        }
                                    })
                                    onChange(changeval)
                                }}
                                mode={"selector"}
                                multiSelector
                                rangeKey={"label"}
                                range={it.options ?? []}
                            >
                                <View className='picker' style={{ color: "#6190E8" }}>
                                    {curval[key] ? it.options.filter(its => its.value == curval[key])[0].label : <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>}
                                </View>
                            </Picker>


                        </View>
                    } else if (type == "input") {
                        return <View height={20} style={{width:'100%'}}>
                            <Input
                                style={{ textAlign: "right", fontSize: 16, color: "#6190E8" }}
                                placeholder="请输入"
                                onBlur={onBlur}
                                onInput={(e) => {
                                    let changeval = newvalue.map(it => {
                                        if (it.id == row.id) {
                                            return {
                                                ...it,
                                                [key]: e.target.value
                                            }
                                        } else {
                                            return {
                                                ...it
                                            }
                                        }
                                    })
                                    onChange(changeval)

                                }}
                                value={curval[key]}
                            />
                        </View>
                    }

                }
            }
        } else {
            return {
                ...it
            }
        }
    })

    return (
        <ListPicker
            onChange={onChange}
            value={value}
            item={item}
            columns={newColumns}
        >
        </ListPicker>
    )
}),
    RenderLists = memo(({ onChange, onBlur, item,value, setValue, setigger, option }) => {
        let alldata = item?.dataSource ??[];
        let newColumns = item?.columns.map(it => {
            if (it?.submittype == "inputnumber") {
                return {
                    ...it,
                    render: (cur, row) => {
                        let { key } = it ?? {};//结构结果
                        let newvalue = value ?? alldata,//初始化idlist
                            curval = newvalue.filter(it => it?.id == row?.id)[0];//当前行val
                        curval = curval ?? {};
                        return <View height={20}>
                            <Input
                                style={{ textAlign: "right", fontSize: 16, color: "#6190E8" }}
                                placeholder="请输入"
                                onBlur={onBlur}
                                onInput={(e) => {
                                    let changeval = newvalue.map(it => {
                                        if (it?.id == row?.id) {
                                            return {
                                                ...it,
                                                [key]:e.target.value
                                            }
                                        } else {
                                            return {
                                                ...it
                                            };
                                        }
                                    })
                                    onChange(changeval)

                                }}
                                value={curval[key]}
                                type='number'
                            />
                        </View>

                    }
                }
            } else {
                return {
                    ...it
                }
            }
        });
        return (
            <ListPicker
                onChange={onChange}
                value={value}
                item={item}
                columns={newColumns}
            >
            </ListPicker>
        )
    },(prev,next)=>{
        return false;
    })
    , RenderAddTable = memo(({ onChange, onBlur, value, item, setValue }) => {
        //获取接口下拉框数据 columns 下 {key:options}
        const [option, setoption] = useState({});
        async function setoptions(currow) {
            let { options, belinked, key } = currow;
            if (!options && !belinked) {
                return
            }

            if (Array.isArray(options)) {
                setoption((opt) => {
                    return {
                        ...opt,
                        [key]: options
                    }
                })
                return options
            }

            if (options?.database) {
                let { database, params } = options,
                    res = await database(params);
                res = res?.data;
                setoption((opt) => {
                    return {
                        ...opt,
                        [key]: res?.data?.dataList
                    }
                })
                return res?.data?.dataList;
            }
        }

        useAsyncEffect(async () => {
            item?.columns.map(async it => {
                await setoptions(it)
            })
        }, [])

        let newColumns = useMemo(() => {
            return item?.columns.map(it => {
                let { key, type } = it;
                if (type) {
                    return {
                        ...it,
                        render: (cur, row) => {
                            let curval = value && value.filter(it => it.id == row.id)[0];//当前行val
                            curval = curval ?? {};
                            let curoptions = option[key] ?? [];

                            if (type == "select") {
                                return <View height={20}>
                                    <Picker
                                        onChange={(e) => {
                                            let index = parseInt(e.detail.value);
                                            let val = curoptions[index].value;
                                            let changeval = value.map(it => {
                                                if (it.id == row.id) {
                                                    return {
                                                        ...it,
                                                        [key]: val
                                                    }
                                                } else {
                                                    return {
                                                        ...it
                                                    }
                                                }
                                            })
                                            onChange(changeval)
                                        }}
                                        mode={"selector"}
                                        multiSelector
                                        rangeKey={"label"}
                                        range={curoptions ?? []}

                                    >
                                        <View className='picker' style={{ color: "#6190E8" }}>
                                            {curval[key] ? curoptions.filter(its => its.value == curval[key])[0].label : <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>}
                                        </View>
                                    </Picker>
                                </View>
                            } else if (type == "input") {
                                return <View height={20}>
                                    <Input
                                        style={{ textAlign: "right", fontSize: 16, color: "#6190E8" }}
                                        placeholder="请输入"
                                        onBlur={onBlur}
                                        onInput={(e) => {
                                            let changeval = value.map(it => {
                                                if (it.id == row.id) {
                                                    return {
                                                        ...it,
                                                        [key]: e.target.value
                                                    }
                                                } else {
                                                    return {
                                                        ...it
                                                    }
                                                }
                                            })
                                            onChange(changeval)

                                        }}
                                        value={curval[key]}
                                    />
                                </View>
                            }

                        }
                    }
                } else {
                    return {
                        ...it
                    }
                }
            })

        }, [option, value])


        return (
            <AddListPicker
                onChange={onChange}
                value={value}
                item={item}
                columns={newColumns}
            >
            </AddListPicker>
        )
    }), RenderJumpSelect = memo(({ onChange, onBlur, value, item, setValue }) => {
        //接收返回数据
        useDidShow(() => {
            let pages = Taro.getCurrentPages();
            let currPage = pages[pages.length - 1];
            let curval = currPage[item?.name[0]];
            if (curval) {
                onChange(curval)
            }
        })
        return (
            <View style={{ fontSize: 16, color: "#666" }} onClick={() => {
                Taro.navigateTo({ url: `/pages/selectpage/index?name=${item?.name[0]}&title=${item?.title}&path=${item?.path}&place=${item?.place}&params=${JSON.stringify(item?.params)}&defaultvalue=${JSON.stringify(value ?? [])}` })
            }}>
                {value && value.length > 0 ? <Text style={{ color: "#6190E8" }}>已选择{value.filter(it => !!it[item.place]).length}项</Text> : "请选择"}
            </View>
        )
    })


let InitForm = ({
    fields,
    submit
}) => {
    let {
        control,
        handleSubmit,
        formState: { errors },
        watch,
        setValue,
        getValues,
        reset
    } = useForm({
        defaultValues: {

        }
    }),
        [option, cop] = useState({}),
        [tigger, setigger] = useState();

    const onSubmit = (data) => {
        let filterkey = Object.keys(fields).filter(it => {
            return fields[it].disabled === true
        })
        if (filterkey) {
            filterkey.map(it => {
                delete data[it]
            })
        }
        submit && submit(data, reset);
    };


    async function setoptions(item) {
        let { options, belinked } = item;
        if (!options && !belinked) {
            return
        }

        if (Array.isArray(options)) {
            return options
        }

        if (options?.database) {
            let { database, params } = options,
                res = await database(params);
            res = res?.data;

            return res?.data?.dataList;
        }

        if (belinked?.options) {
            let { database, params } = belinked.options, newparams = {};
            for (let i in params) {
                if (params[i] == 'linked') {
                    newparams[i] = getValues(i);
                } else {
                    newparams[i] = params[i];
                }
            }

            let res = await database({ ...newparams })
            res = res?.data;
            return res?.data?.dataList;
        }
    }

    useEffect(() => {
        for (let i in fields) {
            fields[i].value && setValue(i, fields[i].value);
        }
    }, [fields])


    useAsyncEffect(async () => {
        for (let i in fields) {
            if (fields[i].type == "select") {
                let resop = await setoptions(fields[i]);
                cop((cur) => ({
                    ...cur,
                    [i]: resop
                }))
            }
        }
    }, [tigger])
    return <View style={{ borderRadius: 8, overflow: "hidden" }} bg-white>
        {
            Object.keys(fields).map((it) => {
                let item = fields[it];
                let { title, required, type, value, hides } = item,
                    controlprops = {
                        key: it,
                        it,
                        value,
                        title,
                        control,
                        required,
                        errors
                    }
                if (type == "input" || type == "password") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops}>
                        <RenderInput item={item}></RenderInput>
                    </ControlDom>
                } else if (type == "select") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops}>
                        <RenderSelect item={item} setValue={setValue} setigger={setigger} option={option}></RenderSelect>
                    </ControlDom>
                } else if (type == "datepicker") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops}>
                        <RenderDatePicker item={item}></RenderDatePicker>
                    </ControlDom>
                } else if (type == "upload") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops} column={() => {
                        let num = watch(it) ? watch(it).length : null
                        return <Text
                            body
                            style={{ color: "#707070", fontSize: 16, paddingRight: 2 }}
                        >{num ? `已选择(${num + "/" + item?.limit})` : <Text style={{ color: "rgba(0,0,0,0.5)" }}>请选择</Text>}</Text>
                    }}>
                        <RenderImagePicker item={item}></RenderImagePicker>
                    </ControlDom>
                } else if (type == "list") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops} column={() => {
                        return <View center height={50}><Text
                            body
                            style={{ color: "#ccc", fontSize: 16, paddingRight: 2 }}
                        ></Text></View>
                    }}>
                        <RenderList item={item}></RenderList>
                    </ControlDom>
                } else if (type == "listsc") {
                    if (hides) {
                        return
                    };
                    return <ControlDom {...controlprops} column={() => {
                        return <View center height={50}><Text
                            body
                            style={{ color: "#ccc", fontSize: 16, paddingRight: 2 }}
                        ></Text></View>
                    }}>
                        <RenderLists item={item} setValue={setValue}></RenderLists>
                    </ControlDom>
                } else if (type == "addtable") {
                    if (hides) {
                        return
                    }

                    return <ControlDom {...controlprops} column={() => {
                        return <View center height={50}><Text
                            body
                            style={{ color: "#ccc", fontSize: 16, paddingRight: 2 }}
                        >{(watch(it) && watch(it).length) ?? 0}/{item.maxlength}</Text></View>
                    }}>
                        <RenderAddTable item={item}></RenderAddTable>
                    </ControlDom>
                } else if (type == "textarea") {
                    if (hides) {
                        return
                    }

                    return <ControlDom {...controlprops} column={() => {
                        return <View center height={50}><Text
                            body
                            style={{ color: "#ccc", fontSize: 16, paddingRight: 2 }}
                        ></Text></View>
                    }}>
                        <RenderTextarea item={item}></RenderTextarea>
                    </ControlDom>
                } else if (type == "jumpselect") {
                    if (hides) {
                        return
                    }
                    return <ControlDom {...controlprops}>
                        <RenderJumpSelect
                            item={item}
                            setValue={setValue}
                            setigger={setigger}
                            option={option}
                        ></RenderJumpSelect>
                    </ControlDom>
                }




            })
        }

        <Button onClick={handleSubmit(onSubmit)} type="primary" style={{ margin: 12, backgroundColor: "#ff4800" }}>
            提交
        </Button>
    </View>

}

export default InitForm
